package Olivia.olivia3d.model.ms3d
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.utils.Dictionary;
	
	public class Ms3dManager extends EventDispatcher
	{		
		//open pipe or parellel
		private static var pipeLining:Boolean = true;
		
		//thread count
		private static var lines:int = 5;
		
		//loaders
		private static var loaderList:Array;
		//loading urls
		private static var loadingUrlList:Array;
		//loading thred count
		private static var loadingLines:int;
		
		//waiting List
		private static var waitList:Array;
		
		//model storage
		public static var models:Dictionary = new Dictionary();
		
		public function Ms3dManager()
		{
			
		}
		
		public static function load(file:String,callBack:Function=null,param:*=null):void
		{
			//models contain(file)
			var res:Ms3dStruct = getModel(file);
			if(!res){
				//go load
				goload(file, callBack, param);
			}else{
				//call back
				if(callBack != null){
					if(param == null){
						callBack.call(null, res);
					}else{
						callBack.call(null, res, param);
					}
				}
				popWaitingRes();
			}
		}
		
		private static function popWaitingRes():void
		{
			// TODO Auto Generated method stub
			if(waitList.length == 0)
				return;
			
			var popArr:Array = waitList.pop();
			load(popArr[0], popArr[1], popArr[2]);
		}
		
		private static function goload(file:String, callBack:Function, param:*):void
		{
			// TODO Auto Generated method stub
			if(loaderList == null){
				loaderList = new Array();
				loadingUrlList = new Array();
				loadingLines = 0;
				waitList = new Array();
			}
			
			//loading this url;
			if(isLoading(file)){
				waitList.push([file,callBack,param]);
			}
			
			var lens:int = loaderList.length;
			if(lens < lines){
				var tempRL:PriMs3dLoader = new PriMs3dLoader();
				loaderList.push(tempRL);
				loadingUrlList.push(file);
				
				if(!pipeLining)
					loadingLines++;
				
				tempRL.addEventListener(Event.COMPLETE, completeLoader);
				tempRL.load(file,callBack,param);
			}else{
				var freeLoader:PriMs3dLoader = findFreeLoader();
				if(freeLoader != null){
					loadingUrlList.push(file);
					
					if(!pipeLining)
						loadingLines++;
					
					freeLoader.load(file, callBack, param);
				}else{
					waitList.push([file, callBack, param]);
				}
			}
		}
		
		private static function findFreeLoader():PriMs3dLoader
		{
			var resLoader:PriMs3dLoader;
			var lens:int = loaderList.length;
			for(var i:int=0; i<lens; ++i)
			{
				var tempLR:PriMs3dLoader = loaderList[i] as PriMs3dLoader;
				if(!tempLR.loading)
				{
					resLoader = tempLR;
					break;
				}
			}
			return resLoader;
		}
		
		protected static function completeLoader(event:Event):void
		{
			var freeLoader:PriMs3dLoader = event.target as PriMs3dLoader;
			if(pipeLining){
				removeLoadingUrl(freeLoader.file);
				
				popWaitingRes();
			}else{
				loadingLines--;
				if(loadingLines == 0)
					clearLoadingUrl();
			}
		}
		
		private static function clearLoadingUrl():void
		{
			loadingUrlList = new Array();
			
			var lens:int = waitList.length;
			if(lens>5)
				lens = 5;
			
			for(var i:int=0; i<lens; ++i){
				popWaitingRes();
			}
		}		
		
		private static function removeLoadingUrl(url:String):void
		{
			var lens:int = loadingUrlList.length;
			for(var i:int=lens-1; i>-1; --i){
				var tempUrl:String = loadingUrlList[i];
				if(tempUrl == url){
					loadingUrlList.splice(i,1);
					break;
				}
			}
		}
		
		private static function isLoading(file:String):Boolean
		{
			// TODO Auto Generated method stub
			var loading:Boolean = false;
			var lens:int = loaderList.length;
			for(var i:int=0; i<lens; ++i){
				var tempUrl:String = loadingUrlList[i];
				if(tempUrl == file){
					loading = true;
					break;
				}
			}
			return loading;
		}
		
		private static function getModel(file:String):Ms3dStruct
		{
			// TODO Auto Generated method stub
			if(models[file] != null){
				var returnRes:Ms3dStruct = models[file];				
				return returnRes;
			}else{
				return null;
			}
		}
	}
}